package nl.weeaboo.sh.danmaku;

import static nl.weeaboo.sh.danmaku.SpellUtil.chain;
import static nl.weeaboo.sh.danmaku.SpellUtil.create;
import static nl.weeaboo.sh.danmaku.SpellUtil.tAngle;
import static nl.weeaboo.sh.danmaku.SpellUtil.tAngleInc;
import static nl.weeaboo.sh.danmaku.SpellUtil.tPos;
import static nl.weeaboo.sh.danmaku.SpellUtil.tSpeed;

import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.geom.Rectangle2D;

import javax.media.opengl.GL;

import nl.weeaboo.game.gl.GLDraw;
import nl.weeaboo.game.gl.GLManager;
import nl.weeaboo.game.input.UserInput;
import nl.weeaboo.game.text.TextRenderer;
import nl.weeaboo.sh.Game;
import nl.weeaboo.sh.danmaku.ColGrid.ColRectMode;
import nl.weeaboo.sh.level.Level;
import nl.weeaboo.sh.level.Room;
import nl.weeaboo.sh.model.DamageRect;
import nl.weeaboo.sh.objects.Player;
import nl.weeaboo.sh.view.CharaImage;

public class UniverseAdapter {

	private Game game;
	private Universe universe;
	private Rectangle bounds;
	private SpriteShotColHandler spriteColHandler;
	
	public UniverseAdapter(Game game, Room room) {
		this.game = game;
		
		int ts = Level.tileSize;
		bounds = new Rectangle(room.getX() * ts, room.getY() * ts,
				room.getWidth() * ts, room.getHeight() * ts);
		universe = new Universe(bounds.width, bounds.height);
		
		spriteColHandler = new SpriteShotColHandler(game, (Level)game.getLevel(), bounds);
	}
	
	//Functions
	int cooldown = 0;
	
	public void update(UserInput input) {
		universe.step();
		
		int ts = Level.tileSize;
		Level level = (Level)game.getLevel();
		Player player = level.getPlayer();
		int px = player.getX() - bounds.x + ts;
		int py = player.getY() - bounds.y + ts;
		
		//Player <-> Shot collisions
		DamageRect a = new DamageRect();
		//long t0 = System.nanoTime();		
		for (int n = 0; n < 3; n++) {
			ColRectMode mode;
			Rectangle rects[];
			if (n == 0) {
				mode = ColRectMode.HIT;
				rects = player.getHitRects();
			} else if (n == 1) {
				mode = ColRectMode.DAMAGE;
				rects = player.getDamageRects();
			} else {
				mode = ColRectMode.SPLASH;
				rects = player.getSplashRects();
			}

			for (Rectangle r : rects) {
				a.x      = px+r.x;
				a.y      = py+r.y;
				a.width  = r.width;
				a.height = r.height;
				if (n > 0) {
					DamageRect dr = (DamageRect)r;
					a.damage      = dr.damage;
					a.knockbackX  = dr.knockbackX;
					a.knockbackY  = dr.knockbackY;
				}
				
				universe.collideRect(spriteColHandler, player, mode, a);
			}			
		}		
		//System.out.printf("P<->S :: %.2fms\n", (float)((System.nanoTime()-t0)/1000000.0));
		
		//Testing stuff
		if (cooldown > 0) {
			cooldown--;
		} else {
			if (input.isKeyDown(KeyEvent.VK_1)) {
				CharaImage i = game.getCharaImage("shot/shot01.png#red1");
				for (float n = 0; n < 512; n += 4.0f) {				
					create(universe, i, 0, chain(tPos(bounds.width/4, bounds.height/2), tAngle(n), tSpeed(5)));
				}
				cooldown = 4;
			}
			if (input.isKeyDown(KeyEvent.VK_2)) {
				CharaImage i = game.getCharaImage("shot/shot01.png#blue1");
				for (float n = 0; n < 512; n += 4.0f) {				
					create(universe, i, 1, chain(tPos(bounds.width*3/4, bounds.height/2), tAngle(n), tSpeed(2)));
				}			
				cooldown = 1;//0;
			}
			if (input.isKeyDown(KeyEvent.VK_3)) {
				CharaImage i = game.getCharaImage("shot/shot01.png#green1");
				for (float n = -127.5f; n <= 127.5f; n += 4.0f) {				
					create(universe, i, 2, chain(tPos(bounds.width/2, bounds.height), tAngle(n), tSpeed(3),
							tAngleInc(Math.signum(n) * 1.0f)));
				}			
				cooldown = 10;
			}
		}
	}
	public void drawBackground(GLManager glm) {
	}
	public void draw(GLManager glm) {
		GL gl = glm.getGL();
		Level level = (Level)game.getLevel();
		int ts = Level.tileSize;

		Rectangle visibleRect = new Rectangle(level.getVisibleRect());
		visibleRect.x -= bounds.x-ts;
		visibleRect.y -= bounds.y-ts;
		
		gl.glPushMatrix();
		glm.translate(bounds.x-ts, bounds.y-ts);
		glm.pushColor();
		glm.setColor(1, 1, 1, 1);
		
		//long time = System.nanoTime();		
		//glm.setBlendMode(BlendMode.LIGHT);
		Rectangle2D.Float r = new Rectangle2D.Float();
		for (ShotModel s : universe) {
			if (!s.visible) continue;
			
			s.getImageBounds(r);			
			if (r.intersects(visibleRect)) {
				s.draw(glm);
			}				
		}
		//glm.setBlendMode(BlendMode.DEFAULT);		
		//System.out.printf("DRAW :: %.2f\n", (float)((System.nanoTime() - time) / 1000000.0));
		
		if (Game.debugDrawHitRects) {
			glm.setTexture(null);
			for (ShotModel s : universe) {
				if (!s.visible) continue;

				s.getImageBounds(r);			
				if (r.intersects(visibleRect)) {
					glm.setColor(1, 0, 0, 0.5f);
					for (ColNode node : s.colNodes) {
						GLDraw.fillRect(gl, s.x+node.x-node.radius, s.y+node.y-node.radius,
								node.radius<<1, node.radius<<1);
					}
				}
			}

			glm.setColor(1, 1, 1, 1);
			TextRenderer tr = game.getImageStore().getTextRenderer("arial", Font.BOLD, 14);
			tr.drawString(glm, String.format("shots: %d", universe.getShots().size()),
					ts+16, ts+8, 7);
		}
		
		glm.popColor();
		gl.glPopMatrix();
	}
	
	//Getters
	public Universe getUniverse() { return universe; }
	public Rectangle getBounds() { return bounds; }
	
	//Setters
	
}
